package edu.geo.mb;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.geo.containers.geom.impl.GeometryFactory;
import edu.geo.containers.geom.impl.Point;
import edu.geo.containers.geomdomain.GeometricDomain;
import edu.geo.containers.geomdomain.Grid;
import edu.geo.dao.impl.GeometricDomainDao;
import edu.geo.db.conn.DBConnection;
import edu.geo.service.IGeometricDomainServiceFacade;
import edu.geo.service.impl.GeometricDomainServiceFacade;

@ManagedBean(name = "geometricDomain")
@SessionScoped
public class GeometricDomainMB implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 4001768854047438366L;
	
	private static final String url = "map.jsp?domain={0}";
	
	private static final Log LOGGER = LogFactory
			.getLog(GeometricDomainMB.class);

	// ------ Servicios ------//

	private IGeometricDomainServiceFacade geometricDomainService;

	// ------ Objetos ------//

	/** Variable que almacena el dominio geometrico seleccionado */
	private GeometricDomain geometricObjectSelected;

	/** Variable que almacena el valor del origen */
	private Point origen;

	/** Usuario */
	private String user;

	/** Variables usadas para almacenar el nuevo origen */
	private int origenX, origenY;
	
	/** */
	private List<GeometricDomain> geometricObjectList;

	private boolean objetoAjustadoBool;

	// -------- I N I T ---------- //

	@PostConstruct
	public void init() {
		GeometricDomainDao geometricDomainDao = new GeometricDomainDao(
				new DBConnection("geodb"));
		geometricDomainService = new GeometricDomainServiceFacade(
				geometricDomainDao);

		// TODO :: Reemplazar cuando se tenga los datos del usuario la sesión */
		this.user = new String("user");

		// Definicion del origen
		this.origen = GeometryFactory.createPoint(0, 0);

		// Inicialización de la Grilla
		inicializarGrilla();

		try {
			// Consulta de dominios geométricos existentes
			this.geometricObjectList = this.geometricDomainService
					.retrieveAll();
		} catch (Exception e) {
			// Assert.assertFalse(true);
		}
	}

	// -------- GETTERS Y SETTERS ------------ //

	public GeometricDomain getGeometricObjectSelected() {
		return geometricObjectSelected;
	}

	public void setGeometricObjectSelected(
			GeometricDomain geometricObjectSelected) {
		this.geometricObjectSelected = geometricObjectSelected;
		// Al cambiar el objeto geométrico se deben volver a validar los puntos
		this.objetoAjustadoBool = false;
	}

	public Point getOrigen() {
		return origen;
	}

	public void setOrigen(Point origen) {
		this.origen = origen;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public int getOrigenX() {
		return origenX;
	}

	public void setOrigenX(int origenX) {
		this.origenX = origenX;
	}

	public int getOrigenY() {
		return origenY;
	}

	public void setOrigenY(int origenY) {
		this.origenY = origenY;
	}

	public boolean isObjetoAjustadoBool() {
		return objetoAjustadoBool;
	}

	public void setObjetoAjustadoBool(boolean objetoAjustadoBool) {
		this.objetoAjustadoBool = objetoAjustadoBool;
	}

	public List<GeometricDomain> getGeometricObjectList() {
		return geometricObjectList;
	}

	public void setGeometricObjectList(List<GeometricDomain> geometricObjectList) {
		this.geometricObjectList = geometricObjectList;
	}

	// -------- M É T O D O S ------------ //

	/**
	 * Método que inicializa un dominio geometrico con los valores por defecto
	 */
	public void inicializarGrilla() {
		this.origenX = 0;
		this.origenY = 0;
		this.geometricObjectSelected = new GeometricDomain();
		this.geometricObjectSelected.setGrid(new Grid());
		this.geometricObjectSelected.setUser(this.user);		
	}

	/**
	 * Método que guarda un dominio geográfico
	 */
	public void guardarDominio() {
		try {
			Point o = GeometryFactory.createPoint(this.origenX, this.origenY);
			this.geometricObjectSelected.getGrid().setOrigin(o);
			
			this.geometricDomainService.save(this.geometricObjectSelected);
			// Consulta de la lista actualizada de los dominios geométricos
			this.geometricObjectList = this.geometricDomainService
					.retrieveAll();
			this.inicializarGrilla();
			this.objetoAjustadoBool = false;
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * Método que elimina un dominio geográfico
	 */
	public void eliminarDominio() {
		try {
			this.geometricDomainService.delete(this.geometricObjectSelected
					.getId());
			this.inicializarGrilla();
			// Consulta de la lista actualizada de los dominios geométricos
			this.geometricObjectList = this.geometricDomainService
					.retrieveAll();
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * Método que valida los puntos de un objeto geométrico ubicados en la
	 * primer grilla.
	 */
	public void validar() {
		
		try {
			// TODO :: Revisar implementación de la validación de los puntos.
			this.setObjetoAjustadoBool(true);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * Método que ajusta los puntos de un objeto geométrico en la segunda
	 * grilla.
	 */
	public void ajustar() {
		try {
			// TODO :: Revisar implementación que ajusta los puntos.
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		}
	}	
	public String getUrl()
	{
		if (this.geometricObjectSelected != null && this.geometricObjectSelected.getId() > 0)
		{
			LOGGER.info(MessageFormat.format(url, Integer.toString(geometricObjectSelected.getId())));
			return MessageFormat.format(url, Integer.toString(geometricObjectSelected.getId()));
		}		
		LOGGER.info("layout-complex.html");
		return "layout-complex.html";
			
	}

}